pub fn convert_base(num_str: &str, to_base: u32) -> String {
    assert!(
        to_base >= 2 && to_base <= 16,
        "to_base should between 2 and 16."
    );

    let num = parser(num_str).expect("inputs should be formated as [num]([base]).");

    BaseSeq::new(num, to_base)
        .map(|digit| NUMBER_CHAR_MAP[digit as usize])
        .collect()
}

const NUMBER_CHAR_MAP: [char; 16] = [
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
];

fn parser(num_str: &str) -> Option<u32> {
    let (num, base) = num_str.split_once('(')?;
    let base = base.strip_suffix(')')?;
    let base = base.parse().ok()?;
    let num = u32::from_str_radix(num, base).ok()?;
    Some(num)
}

/// 对于 num ∈ N+，num = ∑_i ret_i * base_i
#[derive(Debug)]
struct BaseSeq {
    num: u32,
    bases: std::iter::Rev<std::vec::IntoIter<u32>>,
}

impl BaseSeq {
    fn new(num: u32, base: u32) -> Self {
        Self {
            num,
            bases: (0..)
                .map(|n| base.pow(n))
                .take_while(|&n| n <= num)
                .collect::<Vec<_>>()
                .into_iter()
                .rev(),
        }
    }
}

impl Iterator for BaseSeq {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        let base = self.bases.next()?;
        let ret = self.num / base;
        self.num %= base;
        Some(ret)
    }
}
